#include "CDeleteCommand.h"
#include "CUserInterface.h"
#include "CLevelEditor.h"
#include "DoUndoCommands.h"
#include "CLinkRoomCommand.h"
#include "CMultiCommand.h"
#include "ISceneManager.h"
#include "ISceneNode.h"
#include "CSceneObject.h"
#include "IGUITreeCtrl.h"


extern CGlobals* g;
extern CUserInterface* ui;
extern CLevelEditor* editor;

static void copyWithChildren (array<CSceneObject*>* objects, CSceneObject* obj)
{
	objects->push_back(new CSceneObject(*obj));
	TreeNode* node = ui->m_sceneGraphTree->FindNode(obj->m_SceneNode->getID());
	for (TreeNode* child = node->Child; child; child = child->Sibling)
	{
		copyWithChildren(objects, editor->getSceneObjectFromID(child->ID));
	}
}

CDeleteCommand::CDeleteCommand (CSceneObject* object)
{
	ui->removeSceneNodeFromList(object->m_SceneNode->getID(),object->m_SceneNode->isVisible());
	m_object = new CSceneObject(*object);
	m_changeChildrensParents = 0;

	setDescription(stringw(L"delete ") + m_object->m_UserData->getAttributeAsStringW("Name") +
		L"(" + stringw(m_object->m_SceneNode->getID()) + L")");

	if (m_object->m_UserData->getAttributeAsString("!GameType") == "Geometry")
	{
		for (int i=0; i < MAX_ROOM_LINKS; i++)
		{
			m_linkRoomCommand[i] = new CLinkRoomCommand(object->m_SceneNode->getID(), -1, i, -1);
		}
	}
}

CDeleteCommand::~CDeleteCommand ()
{
	if (m_object->m_UserData->getAttributeAsString("!GameType") == "Geometry")
	{
		for (int i=0; i < MAX_ROOM_LINKS; i++)
		{
			m_linkRoomCommand[i]->drop();
		}
	}

	delete m_object;

	if (m_parent)
		m_parent->drop();

	if (m_changeChildrensParents)
		m_changeChildrensParents->drop();
}

void CDeleteCommand::redo ()
{
	if (m_object->m_UserData->getAttributeAsString("!GameType") == "Geometry")
	{
		for (int i=0; i < MAX_ROOM_LINKS; i++)
		{
			m_linkRoomCommand[i]->redo();
		}
	}

	int id = m_object->m_SceneNode->getID();
	m_parent = m_object->m_SceneNode->getParent();
	m_parent->grab();

	TreeNode* node = ui->m_sceneGraphTree->FindNode(id);
	
	if (node)
	{
		m_treeParentId = node->Parent->ID;

		if (node->Child)
		{
			if (m_changeChildrensParents == 0)
			{
				CMultiCommand* multi = new CMultiCommand;
				for (TreeNode* child = node->Child; child; child = child->Sibling)
				{
					//CChangeTreeParentCommand* changeParent = new CChangeTreeParentCommand(child->ID, id, m_treeParentId);
					CDeleteCommand* changeParent = new CDeleteCommand( child->SceneObject );
					multi->addCommand(changeParent);
					changeParent->drop();
				}
				m_changeChildrensParents = multi;
			}
			m_changeChildrensParents->redo();
		}
	}

	for (u32 j = 0; j < editor->m_SceneObjects.size(); ++j)
	{
		if (editor->m_SceneObjects[j]->m_SceneNode->getID() == id)
		{
			editor->setSelectedNode(0);
			//m_object->m_SceneNode->remove();
			g->sceneManager->addToDeletionQueue(m_object->m_SceneNode);
			delete editor->m_SceneObjects[j];
			editor->m_SceneObjects.erase(j);
			break;
		}
	}

	ui->m_sceneGraphTree->DeleteNode(node);
}

void CDeleteCommand::undo ()
{
	CSceneObject* obj = new CSceneObject(*m_object);

	bool bFound = false;
	for (u32 i=0; i < editor->m_SceneObjects.size(); i++)
	{
		if (obj->m_SceneNode->getID() < editor->m_SceneObjects[i]->m_SceneNode->getID())
		{
			editor->m_SceneObjects.insert(obj, i);
			bFound = true;
			break;
		}
	}

	if (!bFound) editor->m_SceneObjects.push_back(obj);
	editor->addObjectToTreeView(obj);

	m_parent->addChild(obj->m_SceneNode);
	m_parent->drop();
	m_parent = 0;

	TreeNode* node = ui->m_sceneGraphTree->FindNode(obj->m_SceneNode->getID());
	TreeNode* parent = ui->m_sceneGraphTree->FindNode(m_treeParentId);
	ui->m_sceneGraphTree->ChangeParent(node, parent);

	if (m_changeChildrensParents != 0)
		m_changeChildrensParents->undo();

	editor->setSelectedNode(obj->m_SceneNode);

	if (m_object->m_UserData->getAttributeAsString("!GameType") == "Geometry")
	{
		for (int i=0; i < MAX_ROOM_LINKS; i++)
		{
			m_linkRoomCommand[i]->undo();
		}
	}
}
